<?php
namespace Project_725;

use Project_725\FC_ApiExcep;
use TwinPeaks\Core as Core;
use TwinPeaks\Core\Http as Http;
use TwinPeaks\Core\CRule;
use TwinPEaks\Core\CFilterParam;

use TwinPeaks\Core\Datatype as Dt;
use Project_725\Datatype as LmDt;

class FC_Api extends Core\CFrontController
{
	const SIGNUP_RID = 1;
	const INVITE_RID = 2;
	const INVITE_WITHDRAWAL = 3;
	
	/**
	 * @var \stdClass
	 */
	private $response;
	
	/**
	 * @var string
	 */
	private $responseJSON;
	
	/**
	 * @return void
	 */
	protected function onCreate()
	{
		Core\CRule::setDefaultAllowedMethods(Http\POST_METHOD);
		parent::onCreate();
		$this->getResponse()->setMediaType(Http\MIME_TYPE_APPLICATION_JSON);
		$this->response = new \stdClass();
		$this->response->header = [];
		$this->setStatus(1); // Assume successful execution
	}
	
	/**
	 * Sets execution status. 
	 * 
	 * @return void
	 */
	function setStatus($status)
	{
		$this->response->header['status'] = intval($status);
	}
	
	/**
	 * @return void
	 */
	function setError($code)
	{
		$this->setStatus(false);
		$this->response->header['error'] = $code;
	}
	
	/**
	 * @return void
	 */
	function setErrorMessage($message)
	{
		$this->setStatus(false);
		$this->response->header['error-message'] = $message;
	}

	/**
	 * @return void
	 */
	protected function defineRules()
	{
		CRule::setURI_pathPrefix('/api/lm');
		CRule::setDefaultController('Controller\API');
		
		$accessTokenParam = Core\CFilterParam::post('access_token', new Dt\CString);		
		$email = CFilterParam::post('email', new Dt\CEmail);
		$pass = Core\CFilterParam::post('pass', new Dt\CString);
		
		$this->addRule(CRule::matchStr('/ping/', 'ping'));

		$this->addRule(CRule::matchStr('/signup/', 'signup', self::SIGNUP_RID))
			->filterAddParam($email)
			->filterAddParam($pass)
			->filterAddParam(CFilterParam::post('sex', new LmDt\Sex));
		
		$this->addRule(CRule::matchStr('/get_access_token/', 'getAccessToken'))
			->filterAddParam(CFilterParam::post('login', new Dt\CString))
			->filterAddParam(CFilterParam::post('pass', new Dt\CString));
		
		$this->addRule(CRule::matchStr('/status/info/', 'getStatusInfo'))
			->filterAddParam($accessTokenParam);		
		
		$this->addRule(CRule::matchStr('/save_loc/', 'saveLocation'))
			->filterAddParam($accessTokenParam)
			->filterAddParam(CFilterParam::post('lat', 'decimal'))
			->filterAddParam(CFilterParam::post('long', 'decimal'));

		$this->addRule(CRule::matchStr('/invite/', 'invite', self::INVITE_RID))
			->filterAddParam($accessTokenParam)
			->filterAddParam($email)
			->filterAddParam(CFilterParam::post('sender_name', new Dt\CString))
			->filterAddParam(CFilterPAram::post('recipient_name', new Dt\CString))
		;
		
		$this->addRule(CRule::matchStr('/invite/withdraw/', 'withdrawInvitation', self::INVITE_WITHDRAWAL))
			->filterAddParam($accessTokenParam)
			->filterAddParam(CFilterParam::post('invite_code', new Dt\CString));
	}
	
	/**
	 * @return void
	 */
	function onRuleExecuted(&$result)
	{		
	}
	
	/**
	 * @return void
	 */
	protected function prepareResponse()
	{
		$this->responseJSON = json_encode($this->response, JSON_FORCE_OBJECT);		
	}
	
	/**
	 * @return void
	 */
	function postRuleExecution(CRule $current)
	{
		$result = $current->getExecutionResult();
		
		if (is_bool($result))
			$this->setStatus($result);
		elseif (is_array($result))
		{
			$this->response->body = [] + $result;
		}
		
		$this->prepareResponse();
		$current->setExecutionResult($this->responseJSON);
	}
	
	/**
	 * @return void
	 */
	function onSelect()
	{
		require_once __DIR__ . '/Lib/base.php';
		self::getApplication()->definePathAlias('template', '@A/View/Mailer/Template');
	}
	
	/**
	 * @return void
	 */
	function onException($excep)
	{
		$this->setStatus(false);
		$config = self::getApplication()->getConfig();
		if ($config->API_show_errors)
		{
			$this->setError($excep->getCode());
			$this->setErrorMessage($excep->getMessage());
		}
		$this->prepareResponse();
		$this->getResponse()->setBody($this->responseJSON);
	}
	
	function onPDOException($excep)
	{
		$this->onException($excep);
	}
	
	/**
	 * @return void
	 */
	function onCommonException($excep)
	{
		$this->onException($excep);
	}
	
	/**
	 * @return void
	 */
	function onSysException($excep)
	{
		$this->onException($excep);
	}
	
	/**
	 * Returns 400 (bad request) instead of 404 status code
	 * 
	 * @return void
	 */
	function onPageNotFound($excep)
	{
		$this->getResponse()->setStatusCode(Http\STATUS_CODE_BAD_REQUEST);
		return Core\BREAK_CASCADE;
	}

	/**
	 * @return void
	 */
	function createPageLayout()
	{	
		return null;
	}
}
